package com.itheima.mp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.itheima.mp.constant.MessageConstant;
import com.itheima.mp.domain.dto.PageDTO;
import com.itheima.mp.domain.po.Address;
import com.itheima.mp.domain.vo.AddressVO;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.enums.UserStatusEnum;
import com.itheima.mp.exception.UserException;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.query.UserQuery;
import com.itheima.mp.service.UserService;
import com.itheima.mp.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public void updateMoney(Map<String, Object> map) {
        Long id = (Long) map.get("id");
        Integer money = (Integer) map.get("money");
        User user = userMapper.selectById(id);
        if (user.getStatus() == UserStatusEnum.FREEZE) {
            throw new UserException(MessageConstant.ACCOUNT_FREEZE);
        }
        if (user.getBalance() - money < 0) {
            throw new UserException(MessageConstant.PAID_FAIL);
        }
        int remainMoney = user.getBalance() - money;
/*
        //第一种方法
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<User>()
                .set(User::getBalance, remainMoney)
                .set(remainMoney == 0, User::getStatus, User.STATUS_DISABLE)
                .eq(User::getId, id);
        userMapper.update(user, wrapper);
*/
        //第二种方法
        lambdaUpdate().set(User::getBalance, remainMoney)
                .set(remainMoney == 0, User::getStatus, UserStatusEnum.FREEZE)
                .eq(User::getBalance, user.getBalance())
                .eq(User::getId, id)
                .update();
    }

    @Override
    public List<User> queryUserList(UserQuery query) {
        return lambdaQuery()
                .like(query.getName() != null, User::getUsername, query.getName())
                .eq(query.getStatus() != null, User::getStatus, query.getStatus())
                .ge(query.getMaxBalance() != null, User::getBalance, query.getMinBalance())
                .le(query.getMinBalance() != null, User::getBalance, query.getMaxBalance())
                .list();
    }

    /**
     * @param id
     * @return
     */
    @Override
    public UserVO getUserAndAddrList(Long id) {
        //查用户
        User user = userMapper.selectById(id);

        //查询地址，用Db或者注入mapper都可以

        List<Address> list = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        List<AddressVO> addressVOList = BeanUtil.copyToList(list, AddressVO.class);
        userVO.setAddressVOList(addressVOList);
        return userVO;
    }

    /**
     * 根据用户们的ids批量查询到用户信息和地址列表
     *
     * @param ids
     * @return
     */
    @Override
    public List<UserVO> getUserAndAddrListByIds(@RequestParam List<Long> ids) {
        List<User> users = userMapper.selectBatchIds(ids);
        if (CollUtil.isEmpty(users)) {
            throw new UserException(MessageConstant.UNKNOWN_ERROR);
        }
        List<UserVO> userVOS = BeanUtil.copyToList(users, UserVO.class);
//        //直接颠覆了以前for循环赋值的操作，直接用集合流操作获取ids然后调用批量操作
        List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
        List<Address> addressList = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();
        //分组获取到用户id对应的addressListVO
        List<AddressVO> addressVOList = BeanUtil.copyToList(addressList, AddressVO.class);
        //存储用户的id和集合
//        Map<Long, Long> collect = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId, Collectors.counting()));
        Map<Long, List<AddressVO>> collect = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
        //封装用户信息
        for (UserVO userVO : userVOS) {
            userVO.setAddressVOList(collect.get(userVO.getId()));
        }


        return userVOS;
    }

    @Override
    public PageDTO<UserVO> getPageCondition(UserQuery query) {
        String name = query.getName();
        Integer status = query.getStatus();
        //分页条件构建
        Page<User> page = query.toMpPage();
        Page<User> userPage = lambdaQuery().like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, status)
                .page(page);
        return PageDTO.of(page, UserVO.class);
    }
}